package com.su.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.su.common.bo.user.UserRegBo;
import com.su.common.constants.ErrorCodeEnum;
import com.su.common.constants.SystemConstants;
import com.su.common.exception.ServiceException;
import com.su.service.IMailService;
import com.su.utils.RedisUtil;
import com.zhenzi.sms.ZhenziSmsClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.su.entity.ItripUser;
import com.su.mapper.ItripUserMapper;
import com.su.service.ItripUserService;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author 大哥
 * @Description :
 * @DateTime : 2021/12/22 8:34
 **/
@Service
public class ItripUserServiceImpl extends ServiceImpl<ItripUserMapper, ItripUser> implements ItripUserService {


    private static final Logger log = LoggerFactory.getLogger(ItripUserServiceImpl.class);

    @Resource
    private ItripUserMapper userMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private IMailService mailService;

    @Value("${context.domain-name}")
    private String domainName;  //域名
    @Value("${sms.apiUrl}")
    private String apiUrl;
    @Value("${sms.appId}")
    private String appId;
    @Value("${sms.appSecret}")
    private String appSecret;

    @Override
    public void checkUser(String userCode) {
        if (!StringUtils.hasText(userCode)){
            throw new ServiceException(ErrorCodeEnum.AUTH_PARAMETER_IS_EMPTY);
        }
        QueryWrapper<ItripUser> query=new QueryWrapper<ItripUser>();
        query.eq("user_code",userCode);
        ItripUser user = userMapper.selectOne(query);
        if (!ObjectUtils.isEmpty(user)){
            throw new ServiceException(ErrorCodeEnum.AUTH_USER_ALREADY_EXISTS);
        }
    }

    @Override
    public ItripUser doregister(UserRegBo userRegBo) {
        if (!StringUtils.hasText(userRegBo.getUserCode())){ //判断账号不为空
            throw new ServiceException(ErrorCodeEnum.AUTH_PARAMETER_IS_EMPTY);
        }else{
            if (ActivateNow(userRegBo.getUserCode(),1)) {
                return null;
            }
        }
        if (!StringUtils.hasText(userRegBo.getUserName())){ //判断昵称不为空
            throw new ServiceException(ErrorCodeEnum.AUTH_PARAMETER_IS_EMPTY);
        }
        if (!StringUtils.hasText(userRegBo.getUserPassword())){ //判断密码不为空
            throw new ServiceException(ErrorCodeEnum.AUTH_PARAMETER_IS_EMPTY);
        }
        if (redisUtil.hasKey("EmailSendNumber:"+userRegBo.getUserCode())){
            int EmailSendNumber =(int)redisUtil.get("EmailSendNumber:" + userRegBo); //当前用户邮箱发送次数
            if (!(EmailSendNumber<3)){
                throw new ServiceException(ErrorCodeEnum.AUTH_MAIL_SEND_NUMBER);
            }
        }
        String md5PWD = SecureUtil.md5(userRegBo.getUserPassword()); //将userRegBo中的密码 md5加密
        userRegBo.setUserPassword(md5PWD);
        ItripUser user=new ItripUser();
        BeanUtils.copyProperties(userRegBo,user);
        user.setActivated(SystemConstants.NOT_ACTIVE); //状态为未激活
        user.setUserType(SystemConstants.REGISTRATION);//用户类型为 自注册用户
        userMapper.insert(user);                        //新增用户
        sendMail(user.getUserCode());
        return user;
    }

    @Override
    public boolean activate(String userCode, String activationCode) {
        if (redisUtil.hasKey("EmailRegCode:"+userCode)){
            String redisActiCode = redisUtil.get("EmailRegCode:" + userCode).toString();
            if (redisActiCode.trim().equals(activationCode.trim())){
                UpdateWrapper<ItripUser> wrapper = new UpdateWrapper<>();
                wrapper.eq("user_code",userCode);
                ItripUser user=new ItripUser();
                user.setActivated(SystemConstants.IS_ACTIVE);
                userMapper.update(user,wrapper);
                redisUtil.del("EmailRegCode:"+userCode);
            }else{
                throw new ServiceException(ErrorCodeEnum.AUTH_ACTIVATIONCODE_ERROR);
            }
        }else{
            throw new ServiceException(ErrorCodeEnum.AUTH_ACTIVATIONCODE_ERROR);
        }

        return true;
    }

    @Override
    public ItripUser userRegister(UserRegBo condition) {
        if (!StringUtils.hasText(condition.getUserCode())){
            throw new ServiceException(ErrorCodeEnum.AUTH_PARAMETER_IS_EMPTY);
        }else{
            if (ActivateNow(condition.getUserCode(),2)) {
                return null;
            }
        }
        if (!StringUtils.hasText(condition.getUserName())){
            throw new ServiceException(ErrorCodeEnum.AUTH_PARAMETER_IS_EMPTY);
        }
        if (!StringUtils.hasText(condition.getUserPassword())){
            throw new ServiceException(ErrorCodeEnum.AUTH_PARAMETER_IS_EMPTY);
        }

        if (redisUtil.hasKey("SMSSendNumber:"+condition.getUserName())){
            int SMSNumber =(int)redisUtil.get("SMSSendNumber:" + condition.getUserName()); //当前用户短信发送次数
            if (!(SMSNumber<3)){
                throw new ServiceException(ErrorCodeEnum.AUTH_PHMAIL_SEND_NUMBER);
            }
        }
        condition.setUserPassword(SecureUtil.md5(condition.getUserPassword()));
        ItripUser user=new ItripUser();
        BeanUtils.copyProperties(condition,user);
        user.setActivated(SystemConstants.NOT_ACTIVE); //状态为未激活
        user.setUserType(SystemConstants.REGISTRATION);//用户类型为 自注册用户
        userMapper.insert(user);                        //新增用户
        sendMsg(user.getUserCode());
        return null;
    }

    @Override
    public boolean activationCode(String userCode, String activationCode) {
        if (redisUtil.hasKey("SMSRegCode:"+userCode)){
            String SMSCode = redisUtil.get("SMSRegCode:" + userCode).toString();
            if (SMSCode.trim().equals(activationCode.trim())){
                UpdateWrapper<ItripUser> wrapper = new UpdateWrapper<>();
                wrapper.eq("user_code",userCode);
                ItripUser user=new ItripUser();
                user.setActivated(SystemConstants.IS_ACTIVE);
                userMapper.update(user,wrapper);
                redisUtil.del("SMSRegCode:"+userCode);
            }else{
                throw new ServiceException(ErrorCodeEnum.AUTH_ACTIVATIONCODE_ERROR);
            }
        }else{
            throw new ServiceException(ErrorCodeEnum.AUTH_ACTIVATIONCODE_ERROR);
        }
        return false;
    }


    public void sendMsg(String to) {
        ZhenziSmsClient client = new ZhenziSmsClient(apiUrl, appId, appSecret);
        Map<String, Object> params = new HashMap<String, Object>();

        params.put("number", to);   //手机号
        params.put("templateId", "6184");   //短信模版
        String activationCode = RandomUtil.randomNumbers(6); //验证码
        params.put("templateParams", new String[]{activationCode});
        try {
            redisUtil.set("SMSRegCode:"+to,activationCode,(60*5));
            if (redisUtil.hasKey("SMSSendNumber:"+to)){
                redisUtil.incr("SMSSendNumber:"+to,1);
            }else{
                redisUtil.set("SMSSendNumber:"+to,1,(60*60)*12);
            }
            String sendMessage = client.send(params);
            log.info("短信返回值:{}",sendMessage);
        } catch (Exception e) {
            log.info(e.getMessage());
            throw new ServiceException(ErrorCodeEnum.AUTH_PHMAIL_SEND_ERROR);
        }
        log.info("激活码:{}",activationCode);


    }

    private void sendMail(String userCode)  {
        String activationCode = RandomUtil.randomString(6); //验证码
        log.info("激活码:{}",activationCode);
        log.info("激活页:{}","<a href=\""+domainName+"api/activate/"+userCode+"/"+activationCode+"\"><a>");
        String content="<html><body>" +
                "<p><img src=\"http://p1.music.126.net/fWV9NB8dFAaVFpp_5x9bMA==/109951166200506365.jpg?param=80y80\">" +
                "你好，感谢你的注册，这是一封验证邮件，请点击下面的连接完成注册，感谢您的支持"+
                "<a href=\""+domainName+"api/activate/"+userCode+"/"+activationCode+"\">激活账户</a>有限期为5分钟"+
                "</p><body></html>";
        try {
            redisUtil.set("EmailRegCode:"+userCode,activationCode,(60*5));
            if (redisUtil.hasKey("EmailSendNumber:"+userCode)){ //判断 EmailSendNumber:userCode key是否存在
                redisUtil.incr("EmailSendNumber:"+userCode,1);
            }else{
                redisUtil.set("EmailSendNumber:"+userCode,1,(60*60)*12);
            }
            mailService.sendHtmlMail(userCode,content);
        } catch (MessagingException e) {
            e.printStackTrace();
            throw new ServiceException(ErrorCodeEnum.AUTH_MAIL_SEND_ERROR);
        }
    }

    /**
     * 判断账号是否激活
     * return 账号存在未激活为true 账号不存在为false
     */
    private boolean ActivateNow(String userCode,int type){
        String verify=type==1? SystemConstants.EMAIL_VERIFY:SystemConstants.PHONE_VERIFY;

        if (ReUtil.isMatch(verify,userCode)){
            QueryWrapper<ItripUser> queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("user_code",userCode);
            ItripUser userByName = userMapper.selectOne(queryWrapper);  //查询是否以存在当前邮箱为账号的用户
            if (!ObjectUtils.isEmpty(userByName)){  //判断查询不为空
                if (userByName.getActivated()==1){  //当前账号以激活
                    throw new ServiceException(ErrorCodeEnum.AUTH_USER_ALREADY_EXISTS);
                }else{ //当前账号未激活
                    if (type==1){
                        sendMail(userCode); //发送邮箱重新激活
                    }else{
                        sendMsg(userCode); //发送短信
                    }
                    return true;
                }
            }
        }else{
            throw new ServiceException(ErrorCodeEnum.AUTH_ILLEGAL_USERCODE);
        }
        return false;
    }


}
